/*
 * Copyright 2020-2021 redragon.dongbin
 *
 * This file is part of redragon-erp/赤龙ERP.

 * redragon-erp/赤龙ERP is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.

 * redragon-erp/赤龙ERP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with redragon-erp/赤龙ERP.  If not, see <https://www.gnu.org/licenses/>.
 */
package com.erp.finance.voucher.service.spring;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import org.redragon.commons.lang.Times;
import org.redragon.framework.annotation.Cache;
import org.redragon.framework.annotation.Cache.CacheType;
import org.redragon.framework.hibernate.data.SnowFlake;
import org.redragon.framework.hibernate.model.Pages;
import org.redragon.framework.util.ShiroUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.erp.common.account.dao.model.GLLedger;
import com.erp.common.account.service.GLLedgerService;
import com.erp.common.je.dao.model.GLJeHead;
import com.erp.common.je.dao.model.GLJeLine;
import com.erp.common.je.service.GLJeHeadService;
import com.erp.common.je.service.GLJeLineService;
import com.erp.common.voucher.util.FinVoucherUtil;
import com.erp.finance.voucher.dao.FinVoucherHeadDao;
import com.erp.finance.voucher.dao.FinVoucherLineDao;
import com.erp.finance.voucher.dao.model.FinVoucherBillR;
import com.erp.finance.voucher.dao.model.FinVoucherHead;
import com.erp.finance.voucher.dao.model.FinVoucherHeadCO;
import com.erp.finance.voucher.dao.model.FinVoucherLine;
import com.erp.finance.voucher.service.FinVoucherBillRService;
import com.erp.finance.voucher.service.FinVoucherHeadService;
import com.erp.masterdata.calendar.dao.model.MdFinanceCalendarPeriod;
import com.erp.masterdata.calendar.service.MdFinanceCalendarPeriodService;

@Service
@Transactional(rollbackFor=Exception.class)
public class FinVoucherHeadServiceImpl implements FinVoucherHeadService {

    //注入Dao
    @Autowired
    private FinVoucherHeadDao finVoucherHeadDao;
    @Autowired
    private FinVoucherLineDao finVoucherLineDao;
    @Autowired
    private FinVoucherBillRService finVoucherBillRService;
    @Autowired
    @Qualifier("glJeHeadServiceCommon")
    private GLJeHeadService glJeHeadService;
    @Autowired
    @Qualifier("glJeLineServiceCommon")
    private GLJeLineService glJeLineService;
    @Autowired
    @Qualifier("glLedgerServiceCommon")
    private GLLedgerService glLedgerService;
    @Autowired
    private MdFinanceCalendarPeriodService mdFinanceCalendarPeriodService;
    
    @Override
    public void insertDataObject(FinVoucherHead obj) {
        this.finVoucherHeadDao.insertDataObject(obj);
    }

    @Override
    public void updateDataObject(FinVoucherHead obj) {
        this.finVoucherHeadDao.updateDataObject(obj);
    }
    
    @Override
    public void insertOrUpdateDataObject(FinVoucherHead obj) {
        this.finVoucherHeadDao.insertOrUpdateDataObject(obj);
    }

    @Override
    public void deleteDataObject(FinVoucherHead obj) {
        this.finVoucherHeadDao.deleteDataObject(obj);
        this.finVoucherLineDao.deleteFinVoucherLineByVoucherHeadCode(obj.getVoucherHeadCode());
        this.finVoucherBillRService.deleteFinVoucherBillRByVoucherHeadCode(obj.getVoucherHeadCode());
    }

    @Override
    public List<FinVoucherHead> getDataObjects() {
        return this.finVoucherHeadDao.getDataObjects();
    }

    @Override
    public FinVoucherHead getDataObject(int id) {
        return this.finVoucherHeadDao.getDataObject(id);
    }

    @Override
    public FinVoucherHead getDataObject(String code) {
        return this.finVoucherHeadDao.getDataObject(code);
    }

    @Override
    public List<FinVoucherHead> getDataObjects(FinVoucherHeadCO paramObj) {
        return this.finVoucherHeadDao.getDataObjects(paramObj);
    }

    @Override
    public List<FinVoucherHead> getDataObjects(Pages pages) {
        return this.finVoucherHeadDao.getDataObjects(pages);
    }
    
    @Override
    public List<FinVoucherHead> getDataObjects(Pages pages, FinVoucherHeadCO paramObj) {
        return this.finVoucherHeadDao.getDataObjects(pages, paramObj);
    }
    
    @Override
    public List<Map<String, Object>> getDataObjectsArray(Pages pages, FinVoucherHeadCO paramObj) {
        return this.finVoucherHeadDao.getDataObjectsArray(pages, paramObj);
    }
    
    @Override
    public List<FinVoucherHead> getDataObjectsForDataAuth(String dataAuthSQL, Pages pages, FinVoucherHeadCO paramObj) {
        return this.finVoucherHeadDao.getDataObjectsForDataAuth(dataAuthSQL, pages, paramObj);
    }
    
    @Override
    public void insertOrUpdateFinVoucher(FinVoucherHead finVoucherHead, List<FinVoucherLine> finVoucherLineList) {
        //编辑头
        this.finVoucherHeadDao.insertOrUpdateDataObject(finVoucherHead);
        //循环编辑行
        for(FinVoucherLine finVoucherLine: finVoucherLineList) {
            this.finVoucherLineDao.insertOrUpdateDataObject(finVoucherLine);
        }
    }
    
    @Override
    public void updateFinVoucherHeadForApproveStatus(Integer voucherHeadId, String status) {
        this.finVoucherHeadDao.updateFinVoucherHeadForStatus(voucherHeadId, status);
    }
    
    @Override
    public void updateFinVoucherHeadForStatus(Integer voucherHeadId, String voucherHeadCode, String approveStatus) {
        this.finVoucherHeadDao.updateFinVoucherHeadForApproveStatus(voucherHeadId, approveStatus);
        this.finVoucherBillRService.deleteFinVoucherBillRByVoucherHeadCode(voucherHeadCode);
    }
    
    @Override
    @Cache(cacheType=CacheType.ALL, cacheSeconds=7200)
    public int getVoucherHeadNum(String startDate, String endDate) {
        return this.finVoucherHeadDao.getVoucherHeadNum(startDate, endDate);
    }
    
    @Override
    public FinVoucherHead getVoucherHead(String billType, String billHeadCode) {
        return this.finVoucherHeadDao.getVoucherHead(billType, billHeadCode);
    }
    
    @Override
    public int getVoucherNumByStatus(String status, String approveStatus, String postStatus, String startDate, String endDate) {
        return this.finVoucherHeadDao.getVoucherNumByStatus(status, approveStatus, postStatus, startDate, endDate);
    }
    
    @Override
    public String postVoucherToJe(Integer headId) {
        //获取子分类账头信息
        FinVoucherHead finVoucherHead = this.finVoucherHeadDao.getDataObject(headId);
        
        //获取子分类账行信息
        List<FinVoucherLine> finVoucherLineList = this.finVoucherLineDao.getFinVoucherLineListByVoucherHeadCode(finVoucherHead.getVoucherHeadCode());
        
        //获取子分类账单据关联信息
        FinVoucherBillR finVoucherBillR = this.finVoucherBillRService.getDataObject(finVoucherHead.getVoucherHeadCode());
        
        //获取主账簿
        GLLedger glLedger  = this.glLedgerService.getPrimaryGLLedgerByLegal(ShiroUtil.getLegalCode());
        
        //获取当前分类账日期的所属期间
        MdFinanceCalendarPeriod mdFinanceCalendarPeriod = this.mdFinanceCalendarPeriodService.getPeriodNameByDate(finVoucherHead.getVoucherDate());
        
        //创建日记账头
        GLJeHead glJeHead = new GLJeHead();
        glJeHead.setJeHeadCode(FinVoucherUtil.incrVoucherNumberCache("JE").toString());
        Times time = new Times();
        glJeHead.setJeName("子分类账 "+time.getDate()+" "+time.getTime());
        glJeHead.setJeDesc("子分类账来源凭证编号 "+finVoucherHead.getVoucherNumber());
        glJeHead.setJeType("SLA");
        if(finVoucherBillR!=null) {
            glJeHead.setJeSource(finVoucherBillR.getBillType());
        }
        glJeHead.setBillNum(finVoucherHead.getBillNum());
        glJeHead.setJeDate(finVoucherHead.getVoucherDate());
        if(mdFinanceCalendarPeriod!=null) {
            glJeHead.setPeriodName(mdFinanceCalendarPeriod.getPeriodName());
        }
        glJeHead.setLedgerCode(glLedger.getLedgerCode());
        glJeHead.setCurrencyCode(glLedger.getCurrencyCode());
        glJeHead.setPostStatus("N");
        glJeHead.setVoucherHeadCode(finVoucherHead.getVoucherHeadCode());
        glJeHead.setStaffCode(finVoucherHead.getStaffCode());
        glJeHead.setDepartmentCode(finVoucherHead.getDepartmentCode());
        this.glJeHeadService.insertDataObject(glJeHead);
        
        //循环分类账行
        for(FinVoucherLine finVoucherLine: finVoucherLineList) {
            //创建日记账行
            GLJeLine glJeLine = new GLJeLine();
            glJeLine.setJeLineCode(SnowFlake.getConcurrentId().toString());
            glJeLine.setJeHeadCode(glJeHead.getJeHeadCode());
            glJeLine.setSubjectCode(finVoucherLine.getSubjectCode());
            glJeLine.setMemo(finVoucherLine.getMemo());
            glJeLine.setCrAmount(finVoucherLine.getCrAmount());
            glJeLine.setDrAmount(finVoucherLine.getDrAmount());
            glJeLine.setVoucherLineCode(finVoucherLine.getVoucherLineCode());
            this.glJeLineService.insertDataObject(glJeLine);
        }
        
        //修改过账状态
        this.finVoucherHeadDao.updateVoucherPostStatus(headId);
        return "过账完成";
    }
    
    @Override
    public void updateVoucherPostStatus(Integer headId) {
        this.finVoucherHeadDao.updateVoucherPostStatus(headId);
    }
    
    @Override
    public List<FinVoucherHead> getFinVoucherHeadPostListByIds(String headIds) {
        return this.finVoucherHeadDao.getFinVoucherHeadPostListByIds(headIds);
    }
    
    @Override
    public List<FinVoucherHead> getFinVoucherHeadPostListByPeriodName(String startDate, String endDate) {
        return this.finVoucherHeadDao.getFinVoucherHeadPostListByPeriodName(startDate, endDate);
    }
    
}